package cn.com.mdx.collection.stack;

import java.util.Iterator;

/**
 * FILO 先进后出
 *
 * @author huangyuan
 * @description 栈 - 链表实现
 */
public class LinkedStack<Item> implements Iterable<Item> {
    /**
     * 栈容量
     */
    private int size;
    /**
     * 指向栈第一个节点
     */
    private Node<Item> head;
    /**
     * 节点类
     */
    private static class Node<Item> {
        /**
         * 数据
         */
        private final Item item;
        /**
         * 指向下个节点的指针
         */
        private final Node<Item> next;

        public Node(Item item, Node<Item> next) {
            this.item = item;
            this.next = next;
        }
    }

    /**
     * @param item 入栈
     * @methodName push
     * @Desc 元素入栈
     * @Author huangyuan
     */
    public void push(Item item) {
        head = new Node<>(item, head);
        size++;

    }

    /**
     * @return Item 出栈元素
     * @methodName pop
     * @Desc 元素出栈
     * @Author huangyuan
     */
    public Item pop() {
        if (isEmpty()) throw new UnsupportedOperationException("栈为空无法进行此操作");
        Item item = head.item;
        head = head.next;
        size--;
        return item;
    }

    /**
     * @return 栈容量
     * @methodName size
     * @Desc 获取栈容量
     * @Author huangyuan
     */
    public int size() {
        return size;
    }

    /**
     * @return false 栈不为空 true 栈为空
     * @methodName isEmpty
     * @Desc 栈是否为空
     * @Author huangyuan
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * @return Iterator 可迭代对象
     * @methodName iterator
     * @Desc
     * @Author huangyuan
     * @Date 2020/7/8 5:45 下午
     */
    @Override
    public Iterator<Item> iterator() {
        return new LinkedStackIterator();
    }

    private class LinkedStackIterator implements Iterator<Item> {
        Node<Item> current = head;
        @Override
        public boolean hasNext() {
            return current != null;
        }

        @Override
        public Item next() {
            Item item = current.item;
            current = current.next;
            return item;
        }
    }

    public static void main(String[] args) {
        LinkedStack<String> linkedStack = new LinkedStack<>();
        linkedStack.push("001");
        linkedStack.push("002");
        System.out.println(linkedStack.pop());
        linkedStack.push("003");
        linkedStack.push("004");
        System.out.println("-----------------------");
        for (String s : linkedStack) System.out.println(s);
        System.out.println("-----------------------");
        System.out.println(linkedStack.pop());
        System.out.println(linkedStack.pop());
        System.out.println(linkedStack.pop());
    }
}
